package com.xiaoluo.common.utils;

import com.xiaoluo.cd.entity.base.Jobs;
import com.xiaoluo.cd.entity.base.Projects;
import com.xiaoluo.cd.entity.base.Version;
import com.xiaoluo.common.enums.JobModeEnum;
import com.xiaoluo.common.enums.JobStatusEnum;
import com.xiaoluo.common.queue.BuildLogMap;
import com.xiaoluo.web.form.ProjectForm;
import freemarker.cache.StringTemplateLoader;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.net.URL;
import java.text.SimpleDateFormat;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 * Project : XL-CD
 * Package : com.xiaoluo.common.utils
 * Created by Willian.
 * Date  : 2016/3/7 16:27.
 */
public class QuickDeployShell {

    private final static Logger logger = LoggerFactory.getLogger(QuickDeployShell.class);
    private final static String PATH_SUFFIX="_temp/";
    private final static String SCRIPT_FILE="/fabfile.py";

    /**
     *
     * @param dir
     */
    private static void createWorkSpace(String dir){
        logger.info("createWorkSpace:{}",dir);
        File file = new File(dir);
        if(!file.exists()){
            file.mkdirs();
        }
        createWorkSpaceForce(dir);
    }

    /**
     *
     * @param dir
     * @return
     */
    private static boolean createWorkSpaceForce(String dir){
        logger.info("createWorkSpaceForce:{}",dir);
        ProcessBuilder pb = new ProcessBuilder("mkdir","-p",dir);
        pb.directory(new File("/"));
        pb.redirectErrorStream(true);
        try {
            Process process = pb.start();
            BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream(),"GBK"));
            String line = reader.readLine();

            while (line != null){
                logger.info("exec:{}",line);
                line = reader.readLine();
            }
            int code = process.waitFor();
            logger.info("code:{}",code);
        } catch (Exception e) {
            e.printStackTrace();
        }

        return false;
    }

    /**
     *
     * @param path
     */
    private static void cleanScript(String path){
        File file = new File(path+SCRIPT_FILE);
        file.delete();
    }

    /**
     * 清空目录
     * @param dir
     * @return
     */
    private static boolean cleanDir(File dir){

        if (dir.isDirectory()) {
            String[] children = dir.list();
            for (int i=0; i<children.length; i++) {
                boolean success = cleanDir(new File(dir, children[i]));
                if (!success) {
                    return false;
                }
            }
        }

        // The directory is now empty so now it can be smoked
        return dir.delete();
    }

    private static String getScript(){
        String fileName = QuickDeployShell.class.getResource("/").getPath()+"fabric.py";
        try {
            FileReader buffer = new FileReader(new File(fileName));
            BufferedReader br = new BufferedReader (buffer);
            StringBuffer script = new StringBuffer();
            try {
                String line;
                while ((line = br.readLine() )!=null) {
                    script.append(line).append("\n");
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            return script.toString();

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }

        return "";
    }
    /**
     *
     * @param
     * @param path
     */
    private static void buildScript(String path,String fileName,String cmd,String serverIp,
                                    String port,
                                    String user,
                                    String password,
                                    String serverDir){

        /**
         * 生成脚本
         */
        try {

            PrintWriter writer = new PrintWriter(new FileOutputStream(path+SCRIPT_FILE));

            Configuration cfg = new Configuration();
            StringTemplateLoader stringLoader = new StringTemplateLoader();
            String script = getScript();

            stringLoader.putTemplate("fabTpl",script);
            cfg.setTemplateLoader(stringLoader);

            try {
                Template tpl = cfg.getTemplate("fabTpl");
                Map<String,String> params = new HashMap<String, String>();
                params.put("projectPath",path);
                params.put("remoteDir",serverDir);
                params.put("fileName",fileName);
                params.put("cmd",cmd);

                /**
                 * 生成host信息
                 */
                StringBuffer hostBuff = new StringBuffer();
                StringBuffer pwdBuff = new StringBuffer();

                hostBuff.append("'").append(user).append("@").append(serverIp).append(":").append(port).append("'");
                pwdBuff.append("'").append(user).append("@").append(serverIp).append(":").append(port).append("': '").append(password).append("'");

                params.put("hosts",hostBuff.toString());
                params.put("passwords",pwdBuff.toString());

                tpl.process(params, writer);
            } catch (TemplateException e) {
                e.printStackTrace();
            }catch (IOException e) {
                e.printStackTrace();
            }

            writer.flush();
            writer.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
    }


    /**
     * 清理目录
     * @param projects
     * @param jobs
     */
    public static void clean(Projects projects,Jobs jobs){
        String path = buildPath();
        File file = new File(path);
        file.delete();
    }

    private static String buildPath(){
        String path = ApplicationContextUtils.propertyConfigurer.getProperty("xl.cd.workspace").toString();
        if(path != null && path.endsWith("/")){
            return path+"temp/"+ UUID.randomUUID().toString()+"/";
        }else {
            return "/temp/"+ UUID.randomUUID().toString()+"/";
        }
    }

    /**
     *
     * @param file
     * @param serverIp
     * @param port
     * @param user
     * @param password
     * @param serverDir
     * @param cmd
     */
    public static String build(MultipartFile file,
                             String serverIp,
                             String port,
                             String user,
                             String password,
                             String serverDir,String cmd){
        logger.info("run task:{}",cmd);

        StringBuffer buffer = new StringBuffer();

        String temp = buildPath();
        String fileName = file.getOriginalFilename();

        /**
         * 1、生成代码工作目录；
         * 2、生成构建脚本;
         * 3、运行构建脚本;
         */
        createWorkSpace(temp);
        cleanScript(temp);
        buildScript(temp,fileName,cmd,serverIp,port,user,password,serverDir);

        try {
            file.transferTo(new File(temp+fileName));
        } catch (IOException e) {
            e.printStackTrace();
        }

        ProcessBuilder pb = new ProcessBuilder("fab","upload");
        pb.directory(new File(temp));
        pb.redirectErrorStream(true);

        try {

            Process process = pb.start();
            BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream(),"GBK"));

            String line = reader.readLine();

            while (line != null){
                logger.info(line);
                buffer.append(line).append("\r");
                line = reader.readLine();
            }
            process.waitFor(60, TimeUnit.MINUTES);
            System.out.println("wait 30 secends.");
            Thread.sleep(1000*30);
            cleanScript(temp);
            cleanDir(new File(temp));
        } catch (IOException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return buffer.toString();
    }

}
